package actor.controller
{
	import actor.Demon;
	import actor.Tower;
	import actor.attribute.TowerAttribute;
	import actor.event.TowerEvent;
	
	import capricornus.core.RefreshManager;
	import capricornus.events.RefreshEvent;
	
	import components.bullets.BulletManager;
	import components.bullets.BulletVO;
	
	import flash.utils.Dictionary;
	
	import scene.Scene;

	public class TowerAttackController
	{
		private var _attribute:TowerAttribute;
		protected var _tower:Tower;
		
		private var _attackSpeed:int;
		private var _damage:int;
		private var _range:int;
		
		private var _isStart:Boolean = false;
		private var _lastTime:int = 0;
		
		private var _attackDemon:Demon;
		private var _arrDemons:Array;
		private var _dictDemons:Dictionary;
		
		public function TowerAttackController( tower:Tower )
		{
			_tower = tower;
			init();
		}
		
		private function init():void
		{
			_dictDemons = new Dictionary();
			_arrDemons = new Array();
			
			_attribute = _tower.attribute as TowerAttribute;
			_attribute.addEventListener( TowerEvent.ATTACK_SPEED_CHANGE, onAttackSpeedChanged, false, 0, true );
			_attribute.addEventListener( TowerEvent.DAMAGE_CHANGE, onDamageChanged, false, 0, true );
			_attribute.addEventListener( TowerEvent.RANGE_CHANGE, onRangeChanged, false, 0, true );
			
			_tower.addEventListener( TowerEvent.UPGRADE_COMPLETE, onUpgradeComplete, false, 0, true );
			
			_tower.addEventListener( TowerEvent.ATTACK_ME, onDemonCome, false, 0, true );
		}
		
		public function start():void
		{
			_isStart = true;
		}
		
		public function stop():void
		{
			_isStart = false;
		}
		
		public function refresh( time:uint ):void
		{
			if( !_isStart ) return;
			
			_lastTime += time;
			
			if( _lastTime >= _attackSpeed )
			{
				var n:int = _lastTime / _attackSpeed;
				_lastTime -= n * _attackSpeed;
				
				var bc:int = _attribute.bulletCount;
				var i:int;
				if( bc > 1 )
				{
					//多重箭
					for( i=0; i<n; i++ )
					{
						if( !multishot( bc ) ) break;
					}
				}
				else
				{
					for( i=0; i<n; i++ )
					{
						findDemon();
						if( _attackDemon != null )
						{
							attack( _attackDemon );
						}
						else
						{
							stop();
							break;
						}
					}
				}
			}
		}
		
		private function onDemonCome( e:TowerEvent ):void
		{
			var demon:Demon = e.data as Demon;
			if( _dictDemons[demon]==null )
			{
				_dictDemons[demon] = demon;
				for( var i:int=0; i<_arrDemons.length; i++ )
				{
					var d:Demon = _arrDemons[i];
					if( d.pastLength >= demon.pastLength )
					{
						_arrDemons.splice( i, 0, demon );
						break;
					}
				}
				if( i >= _arrDemons.length )
				{
					_arrDemons.push( demon );
				}
				
				start();
			}
		}
		
		/**
		 * 攻击。暴击、秒杀啥的都可以在这里处理 
		 * @param demon
		 * 
		 */		
		private function attack( demon:Demon ):void
		{
			var vo:BulletVO = new BulletVO();
			vo.tower = _tower;
			vo.bulletID = _attribute.bulletID;
			var isCS:Boolean = false;
			var damage:int = _damage;
			if( _attribute.criticalStrikeRate > 0 )
			{
				if( Math.random() <= _attribute.criticalStrikeRate )
				{
					isCS = true;
					damage = damage * (1 + _attribute.criticalStrikeMulti);
				}
			}
			if( _attribute.stunRate > 0 )
			{
				if( Math.random() <= _attribute.stunRate )
				{
					vo.isStun = true;
					vo.stunDuration = _attribute.stunDuration;
					damage += _attribute.stunDamage;
				}
			}
			if( isCS )
			{
				_tower.showCriticalStrikeTips( damage );
			}
			vo.damage = damage;
			vo.demon = demon;
			_tower.attack();
			BulletManager.instance.shoot( vo );
		}
		
		private function multishot( bc:int ):Boolean
		{
			if( Scene.instance.demonCount > 0 )
			{
				var x:int;
				var y:int;
				var len:int = _arrDemons.length - 1;
				var b:Boolean = true;
				for( ; len>=0 && bc > 0; len-- )
				{
					_attackDemon = _arrDemons[len];
					x = _attackDemon.x - _tower.x;
					y = _attackDemon.y - _tower.y;
					if( _attackDemon.isLive() && x * x + y * y <= _range )
					{
						b = false;
						bc--;
						attack( _attackDemon );
					}
					else
					{
						_arrDemons.splice( len, 1 );
						delete _dictDemons[_attackDemon];
					}
				}
				
				if( b )
				{
					_arrDemons.length = 0;
					_attackDemon = null;
					return false;
				}
				else
				{
					return true;
				}
			}
			return false;
		}
		
		private function findDemon():void
		{
			if( Scene.instance.demonCount > 0 )
			{
				var x:int;
				var y:int;
				if( _attackDemon != null && _attackDemon.isLive() )
				{
					x = _attackDemon.x - _tower.x;
					y = _attackDemon.y - _tower.y;
					if( x * x + y * y <= _range )
					{
						return;
					}
				}
				var len:int = _arrDemons.length - 1;
				for( ; len>=0; len-- )
				{
					_attackDemon = _arrDemons[len];
					x = _attackDemon.x - _tower.x;
					y = _attackDemon.y - _tower.y;
					if( _attackDemon.isLive() && x * x + y * y <= _range )
					{
						return;
					}
					else
					{
						_arrDemons.splice( len, 1 );
						delete _dictDemons[_attackDemon];
					}
				}
				
				_arrDemons.length = 0;
				_attackDemon = null;
			}
		}
		
		private function onUpgradeComplete( e:TowerEvent ):void
		{
			_attackSpeed = _attribute.attackSpeed;
			_damage = _attribute.damage;
			_range = _attribute.range * _attribute.range;
		}
		
		private function onAttackSpeedChanged( e:TowerEvent ):void
		{
			_attackSpeed = _attribute.attackSpeed;
		}
		
		private function onDamageChanged( e:TowerEvent ):void
		{
			_damage = _attribute.damage;
		}
		
		private function onRangeChanged( e:TowerEvent ):void
		{
			_range = _attribute.range * _attribute.range;
		}
	}
}
















